|
Hygienic macros are macros whose expansion is guaranteed not to cause the accidental capture of identifiers. They are a feature of programming languages such as Scheme〔 and Dylan. The general problem of accidental capture was well known within the Lisp community prior to the introduction of hygienic macros. Macro writers would use language features that would generate unique identifiers (e.g., gensym) or use obfuscated identifiers in order to avoid the problem. Hygienic macros are a programmatic solution to the capture problem that is integrated into the macro expander itself. The term "hygiene" was coined in Kohlbecker et al.'s 1986 paper that introduced hygienic macro expansion, inspired by the terminology used in mathematics. ==The hygiene problem== In programming languages that have non-hygienic macro systems, it is possible for existing variable bindings to be hidden from a macro by variable bindings that are created during its expansion. In C, this problem can be illustrated by the following fragment: Running the above through the C preprocessor produces: The variable a declared in the top scope is shadowed by the a variable in the macro, which introduces a new scope. As a result, it is never altered by the execution of the program, as the output of the compiled program shows: a is now 0, b is now 1 The simplest solution is to give the macros variables names that do not conflict with any variable in the current program: Until a variable named INCIa is created, this solution produces the correct output: a is now 1, b is now 1 The problem is solved for the current program, but this solution is not robust. The variables used inside the macro and those in the rest of the program have to be kept in sync by the programmer. Specifically, using the macro INCI on a variable INCIa is going to fail in the same way that the original macro failed on a variable a. The "hygiene problem" can extend beyond variable bindings. Consider this Common Lisp macro: While there are no references to variables in this macro, it assumes the symbols "if", "not", and "progn" are all bound to their usual definitions. If, however the above macro is used in the following code: The definition of "not" has been locally altered and so the expansion of my-unless changes. (Redefining standard functions and operators, globally or locally, actually invokes undefined behavior according to ANSI Common Lisp. Such usage can be diagnosed by the implementation as erroneous.) On the other hand, hygienic macro systems preserve the lexical scoping of all identifiers (such as "if" and "not") automatically. This property is called ''referential transparency''. Of course, the problem can occur for program-defined functions which are not protected in the same way: The Common Lisp solution to this problem is to use packages. The my-unless macro can reside in its own package, where user-defined-operator is a private symbol in that package. The symbol user-defined-operator occurring in the user code will then be a different symbol, unrelated to the one used in the macro.Meanwhile, languages such as Scheme that use hygienic macros prevent accidental capture and ensure referential transparency automatically as part of the macro expansion process. In cases where accidental capture is desired, some systems allow the programmer to explicitly violate the hygiene mechanisms of the macro system. For example, the following Scheme implementation of my-unless will have the desired behavior:抄文引用元・出典: フリー百科事典『 ウィキペディア(Wikipedia)』 ■ウィキペディアで「hygienic macro」の詳細全文を読む スポンサード リンク
|